package centerberg.engine;

import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Rectangle2D;

/**
 * The physical representation for a game object. This representation is
 * separate from the graphical representation so care must be taken to
 * update that as well when the
 * {@link PhysicsObject#translated(double, double)} function is called.
 * 
 * @author Andreas
 * @see PhysicsObject
 */
public class PhysicalRepresentation
{
    private Area            collisionArea;
    private AffineTransform transform;
    private Shape           shape;
    
    /**
     * Creates a new physical representation.
     * 
     * @param shape the shape of the physical object
     */
    public PhysicalRepresentation(Shape shape)
    {
        this.shape = shape;
        this.transform = new AffineTransform();
        updateCollisionArea();
    }
    
    /**
     * Returns the collision area.
     * 
     * @return the collision area
     */
    public Area getArea()
    {
        return collisionArea;
    }
    
    /**
     * Returns the non-transformed shape of this physical representation.
     * 
     * @return the non-transformed shape
     */
    public Shape getShape()
    {
        return shape;
    }
    
    /**
     * Returns the current transfrmation. Internal use.
     * 
     * @return the current transformation
     */
    AffineTransform getTransform()
    {
        return transform;
    }
    
    /**
     * Shears the shape by the given k. Maintains left x-coordinate.
     * 
     * @param shy the k to shear by
     */
    public void shear(double shy)
    {
        if (!(shape instanceof Rectangle2D))
            throw new IllegalStateException("Trying to shear a circle, can only do rectangles");
        
        transform.shear(0, shy);
        translate(0, -shape.getBounds2D().getMinX() * shy); // translate calls update
    }
    
    /**
     * Moves the collision area
     * 
     * @param dx
     * @param dy 
     */
    public void translate(double dx, double dy)
    {
        transform.translate(dx, dy);
        updateCollisionArea();
    }
    
    /**
     * Updates the collision area.
     */
    private void updateCollisionArea()
    {
        collisionArea = new Area(shape);
        collisionArea.transform(transform);
    }
}
